});
-const SearchTab = new Lang.Class({
- Name: 'SearchTab',
- Extends: BaseTab,
+const ViewSelector = new Lang.Class({
+ Name: 'ViewSelector',
+
+ _init : function(searchEntry, showAppsButton) {
+ this.actor = new St.BoxLayout({ name: 'viewSelector',
+ vertical: true });
+
+ this._showAppsButton = showAppsButton;
+ this._showAppsButton.connect('notify::checked', Lang.bind(this,
+ function() {
+ if (this._showAppsButton.checked)
+ this._switchTab(this._appsTab);
+ else
+ this._switchTab(this._windowsTab);
+ }));
+
+ // The page area holds the tab pages. Every page is given the
+ // area's full allocation, so that the pages would appear on top
+ // of each other if the inactive ones weren't hidden.
+ this._pageArea = new Shell.Stack();
+ this.actor.add(this._pageArea, { x_fill: true,
+ y_fill: true,
+ expand: true });
+
+ this._tabs = [];
+ this._activeTab = null;
- _init: function(searchEntry) {
this.active = false;
this._searchPending = false;
this._searchTimeoutId = 0;
this._entry = searchEntry;
ShellEntry.addContextMenu(this._entry);
+
this._text = this._entry.clutter_text;
+ this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
this._text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
+ this._text.connect('key-focus-in', Lang.bind(this, function() {
+ this._searchResults.highlightDefault(true);
+ }));
+ this._text.connect('key-focus-out', Lang.bind(this, function() {
+ this._searchResults.highlightDefault(false);
+ }));
+ this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
+ global.stage.connect('notify::key-focus', Lang.bind(this, this._onStageKeyFocusChanged));
this._inactiveIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-find',
this._entry.set_secondary_icon(this._inactiveIcon);
this._iconClickedId = 0;
+ this._capturedEventId = 0;
- this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
- this.parent(new St.Bin() /* Dummy */, this._searchResults.actor, _("Search"), 'edit-find');
-
- this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
- this._text.connect('key-press-event', Lang.bind(this, function (o, e) {
- // We can't connect to 'activate' here because search providers
- // might want to do something with the modifiers in activateDefault.
- let symbol = e.get_key_symbol();
- if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
- if (this._searchTimeoutId > 0) {
- Mainloop.source_remove(this._searchTimeoutId);
- this._doSearch();
- }
- this._searchResults.activateDefault();
- return true;
- }
- return false;
- }));
+ this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
+ this._windowsTab = new ViewTab('windows', _("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
+ this._addViewTab(this._windowsTab);
- this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
+ let appView = new AppDisplay.AllAppDisplay();
+ this._appsTab = new ViewTab('applications', _("Applications"), appView.actor, 'system-run');
+ this._addViewTab(this._appsTab);
- global.stage.connect('notify::key-focus', Lang.bind(this, this._onStageKeyFocusChanged));
+ this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
+ this._searchTab = new BaseTab(new St.Bin(), this._searchResults.actor, _("Search"), 'edit-find');
+ this._addTab(this._searchTab);
- this._capturedEventId = 0;
+ // Default search providers
+ // Wanda comes obviously first
+ this.addSearchProvider(new Wanda.WandaSearchProvider());
+ this.addSearchProvider(new AppDisplay.AppSearchProvider());
+ this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
+ this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
- this._text.connect('key-focus-in', Lang.bind(this, function() {
- this._searchResults.highlightDefault(true);
- }));
- this._text.connect('key-focus-out', Lang.bind(this, function() {
- this._searchResults.highlightDefault(false);
- }));
+ // Load remote search providers provided by applications
+ RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
// Since the entry isn't inside the results container we install this
// dummy widget as the last results container child so that we can
this._searchResults.actor.add_actor(this._focusTrap);
global.focus_manager.add_group(this._searchResults.actor);
+
+ Main.overview.connect('item-drag-begin',
+ Lang.bind(this, this._resetShowAppsButton));
+
+ this._stageKeyPressId = 0;
+ Main.overview.connect('showing', Lang.bind(this,
+ function () {
+ this._resetShowAppsButton();
+ this._stageKeyPressId = global.stage.connect('key-press-event',
+ Lang.bind(this, this._onStageKeyPress));
+ }));
+ Main.overview.connect('hiding', Lang.bind(this,
+ function () {
+ this._resetShowAppsButton();
+ if (this._stageKeyPressId != 0) {
+ global.stage.disconnect(this._stageKeyPressId);
+ this._stageKeyPressId = 0;
+ }
+ }));
+
+ // Public constraints which may be used to tie actors' height or
+ // vertical position to the current tab's content; as the content's
+ // height and position depend on the view selector's style properties
+ // (e.g. font size, padding, spacing, ...) it would be extremely hard
+ // and ugly to get these from the outside. While it would be possible
+ // to use position and height properties directly, outside code would
+ // need to ensure that the content is properly allocated before
+ // accessing the properties.
+ this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
+ coordinate: Clutter.BindCoordinate.HEIGHT });
+ },
+
+ show: function() {
+ this._workspacesDisplay.show();
+
+ if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
+ Main.overview.fadeOutDesktop();
+ },
+
+ zoomFromOverview: function() {
+ this._workspacesDisplay.zoomFromOverview();
+
+ if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
+ Main.overview.fadeInDesktop();
},
hide: function() {
- this.parent();
+ this._workspacesDisplay.hide();
+ },
+
+ _addTab: function(tab) {
+ tab.page.hide();
+ this._pageArea.add_actor(tab.page);
+ tab.connect('activated', Lang.bind(this, function(tab) {
+ this._switchTab(tab);
+ }));
+ },
+
+ _addViewTab: function(viewTab) {
+ this._tabs.push(viewTab);
+ this._addTab(viewTab);
+ },
+
+ _switchTab: function(tab) {
+ let firstSwitch = this._activeTab == null;
+
+ if (this._activeTab && this._activeTab.visible) {
+ if (this._activeTab == tab)
+ return;
+ this._activeTab.hide();
+ }
+
+ if (tab != this._searchTab) {
+ this._activeTab = tab;
+ if (this._searchTab.visible) {
+ this._searchTab.hide();
+ }
+ }
+
+ // Only fade when switching between tabs,
+ // not when setting the initially selected one.
+ if (!tab.visible)
+ tab.show(!firstSwitch);
+ },
+
+ switchTab: function(id) {
+ for (let i = 0; i < this._tabs.length; i++)
+ if (this._tabs[i].id == id) {
+ this._switchTab(this._tabs[i]);
+ break;
+ }
+ },
+
+ _resetShowAppsButton: function() {
+ this._showAppsButton.checked = false;
+ },
+
+ _onStageKeyPress: function(actor, event) {
+ let modifiers = event.get_state();
+ let symbol = event.get_key_symbol();
+
+ if (symbol == Clutter.Escape) {
+ if (this.active)
+ this.reset();
+ else
+ Main.overview.hide();
+ return true;
+ } else if (Clutter.keysym_to_unicode(symbol) ||
+ (symbol == Clutter.BackSpace && this.active)) {
+ this.startSearch(event);
+ } else if (!this.active) {
+ if (symbol == Clutter.Tab) {
+ this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
+ return true;
+ } else if (symbol == Clutter.ISO_Left_Tab) {
+ this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ _searchCancelled: function() {
+ this._switchTab(this._activeTab);
// Leave the entry focused when it doesn't have any text;
// when replacing a selected search term, Clutter emits
}
},
- addSearchProvider: function(provider) {
- this._searchSystem.registerProvider(provider);
- this._searchResults.createProviderMeta(provider);
- },
-
- removeSearchProvider: function(provider) {
- this._searchSystem.unregisterProvider(provider);
- this._searchResults.destroyProviderMeta(provider);
- },
-
startSearch: function(event) {
global.stage.set_key_focus(this._text);
this._text.event(event, false);
this.reset();
}));
}
- this._activate();
+ this._switchTab(this._searchTab);
} else {
if (this._iconClickedId > 0)
this._entry.disconnect(this._iconClickedId);
this._iconClickedId = 0;
this._entry.set_secondary_icon(this._inactiveIcon);
- this.emit('search-cancelled');
+ this._searchCancelled();
}
if (!this.active) {
if (this._searchTimeoutId > 0) {
this.reset();
return true;
}
+ } else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
+ // We can't connect to 'activate' here because search providers
+ // might want to do something with the modifiers in activateDefault.
+ if (this._searchTimeoutId > 0) {
+ Mainloop.source_remove(this._searchTimeoutId);
+ this._doSearch();
+ }
+ this._searchResults.activateDefault();
+ return true;
} else if (this.active) {
let arrowNext, nextDirection;
if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
let text = this._text.get_text().replace(/^\s+/g, '').replace(/\s+$/g, '');
this._searchResults.doSearch(text);
- return false;
- }
-});
-
-
-const ViewSelector = new Lang.Class({
- Name: 'ViewSelector',
-
- _init : function(searchEntry, showAppsButton) {
- this.actor = new St.BoxLayout({ name: 'viewSelector',
- vertical: true });
-
- this._showAppsButton = showAppsButton;
- this._showAppsButton.connect('notify::checked', Lang.bind(this,
- function() {
- if (this._showAppsButton.checked)
- this._switchTab(this._appsTab);
- else
- this._switchTab(this._windowsTab);
- }));
-
- // The page area holds the tab pages. Every page is given the
- // area's full allocation, so that the pages would appear on top
- // of each other if the inactive ones weren't hidden.
- this._pageArea = new Shell.Stack();
- this.actor.add(this._pageArea, { x_fill: true,
- y_fill: true,
- expand: true });
-
- this._tabs = [];
- this._activeTab = null;
-
- this._searchTab = new SearchTab(searchEntry);
- this._addTab(this._searchTab);
-
- this._searchTab.connect('search-cancelled', Lang.bind(this,
- function() {
- this._switchTab(this._activeTab);
- }));
-
- this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
- this._windowsTab = new ViewTab('windows', _("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
- this._addViewTab(this._windowsTab);
-
- let appView = new AppDisplay.AllAppDisplay();
- this._appsTab = new ViewTab('applications', _("Applications"), appView.actor, 'system-run');
- this._addViewTab(this._appsTab);
-
- // Default search providers
- // Wanda comes obviously first
- this.addSearchProvider(new Wanda.WandaSearchProvider());
- this.addSearchProvider(new AppDisplay.AppSearchProvider());
- this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
- this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
-
- // Load remote search providers provided by applications
- RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
-
- Main.overview.connect('item-drag-begin',
- Lang.bind(this, this._resetShowAppsButton));
-
- this._stageKeyPressId = 0;
- Main.overview.connect('showing', Lang.bind(this,
- function () {
- this._resetShowAppsButton();
- this._stageKeyPressId = global.stage.connect('key-press-event',
- Lang.bind(this, this._onStageKeyPress));
- }));
- Main.overview.connect('hiding', Lang.bind(this,
- function () {
- this._resetShowAppsButton();
- if (this._stageKeyPressId != 0) {
- global.stage.disconnect(this._stageKeyPressId);
- this._stageKeyPressId = 0;
- }
- }));
-
- // Public constraints which may be used to tie actors' height or
- // vertical position to the current tab's content; as the content's
- // height and position depend on the view selector's style properties
- // (e.g. font size, padding, spacing, ...) it would be extremely hard
- // and ugly to get these from the outside. While it would be possible
- // to use position and height properties directly, outside code would
- // need to ensure that the content is properly allocated before
- // accessing the properties.
- this.constrainHeight = new Clutter.BindConstraint({ source: this._pageArea,
- coordinate: Clutter.BindCoordinate.HEIGHT });
- },
-
- show: function() {
- this._workspacesDisplay.show();
-
- if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
- Main.overview.fadeOutDesktop();
- },
-
- zoomFromOverview: function() {
- this._workspacesDisplay.zoomFromOverview();
-
- if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
- Main.overview.fadeInDesktop();
- },
-
- hide: function() {
- this._workspacesDisplay.hide();
- },
-
- _addTab: function(tab) {
- tab.page.hide();
- this._pageArea.add_actor(tab.page);
- tab.connect('activated', Lang.bind(this, function(tab) {
- this._switchTab(tab);
- }));
- },
-
- _addViewTab: function(viewTab) {
- this._tabs.push(viewTab);
- this._addTab(viewTab);
- },
-
- _switchTab: function(tab) {
- let firstSwitch = this._activeTab == null;
-
- if (this._activeTab && this._activeTab.visible) {
- if (this._activeTab == tab)
- return;
- this._activeTab.hide();
- }
-
- if (tab != this._searchTab) {
- this._activeTab = tab;
- if (this._searchTab.visible) {
- this._searchTab.hide();
- }
- }
-
- // Only fade when switching between tabs,
- // not when setting the initially selected one.
- if (!tab.visible)
- tab.show(!firstSwitch);
- },
-
- switchTab: function(id) {
- for (let i = 0; i < this._tabs.length; i++)
- if (this._tabs[i].id == id) {
- this._switchTab(this._tabs[i]);
- break;
- }
- },
-
- _resetShowAppsButton: function() {
- this._showAppsButton.checked = false;
- },
-
- _onStageKeyPress: function(actor, event) {
- let modifiers = event.get_state();
- let symbol = event.get_key_symbol();
-
- if (symbol == Clutter.Escape) {
- if (this._searchTab.active)
- this._searchTab.reset();
- else
- Main.overview.hide();
- return true;
- } else if (Clutter.keysym_to_unicode(symbol) ||
- (symbol == Clutter.BackSpace && this._searchTab.active)) {
- this._searchTab.startSearch(event);
- } else if (!this._searchTab.active) {
- if (symbol == Clutter.Tab) {
- this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
- return true;
- } else if (symbol == Clutter.ISO_Left_Tab) {
- this._activeTab.page.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
- return true;
- }
- }
return false;
},
addSearchProvider: function(provider) {
- this._searchTab.addSearchProvider(provider);
+ this._searchSystem.registerProvider(provider);
+ this._searchResults.createProviderMeta(provider);
},
removeSearchProvider: function(provider) {
- this._searchTab.removeSearchProvider(provider);
+ this._searchSystem.unregisterProvider(provider);
+ this._searchResults.destroyProviderMeta(provider);
}
});
Signals.addSignalMethods(ViewSelector.prototype);